﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Narwhunderful.Aphelia.Framework.Graphics
{

    public class BasicSpriteComponent : DrawableComponent, IBasicSpriteComponent
    {

        public BasicSpriteComponent(Game game)
            : base(game)
        {
            base.MiddlegroundIsVisible = true;
        }

        #region IUpdatableComponent

        protected override void InternalUpdate(GameTime gameTime)
        {
            UpdateRenderLocation(gameTime);
            UpdateBounds(gameTime);
        }

        protected internal virtual void UpdateRenderLocation(GameTime gameTime)
        {
            _renderLocation = _location;
        }

        protected internal virtual void UpdateBounds(GameTime gameTime)
        {
            _bounds = new Rectangle((int)_location.X, (int)_location.Y, _sourceRectangle.Width, _sourceRectangle.Height);
        }

        #endregion

        #region IDrawableComponent

        protected virtual bool CanDrawTexture(GameTime gameTime)
        {
            if (_textureInformation == null) return false;
            return (_textureInformation.Texture != null);
        }

        protected virtual void InternalDrawTexture(GameTime gameTime)
        {
            _spriteBatch.Draw(_textureInformation.Texture, _renderLocation, _sourceRectangle, _tintColor);
        }

        protected override void InternalDrawMiddleground(GameTime gameTime)
        {
            base.InternalDrawMiddleground(gameTime);
            if (CanDrawTexture(gameTime)) InternalDrawTexture(gameTime);
        }

        #endregion

        #region IBasicSpriteComponent

        public event EventHandler<EventArgs> LocationChanged = null;
        public event EventHandler<EventArgs> SizeChanged = null;


        SpriteBatch _spriteBatch;
        public virtual SpriteBatch SpriteBatch
        {
            get
            {
                return _spriteBatch;
            }
            set
            {
                _spriteBatch = value;
            }
        }

        TextureInformation _textureInformation;
        public virtual TextureInformation TextureInformation
        {
            get
            {
                return _textureInformation;
            }
            protected set
            {
                _textureInformation = value;
            }
        }

        public Texture2D Texture
        {
            get
            {
                return _textureInformation.Texture;
            }
            set
            {
                if (_textureInformation == null)
                {
                    _textureInformation = new TextureInformation(base.Game, value);
                }
                else
                {
                    _textureInformation.Texture = value;
                }
            }
        }

        Vector2 _renderLocation = Vector2.Zero;
        public Vector2 RenderLocation
        {
            get
            {
                return _renderLocation;
            }
            protected set
            {
                _renderLocation = value;
            }
        }

        Vector2 _location = Vector2.Zero;
        public virtual Vector2 Location
        {
            get
            {
                return _location;
            }
            set
            {
                if (_location != value)
                {
                    _location = value;
                    base.NeedsUpdate = true;
                    OnLocationChanged();
                }
            }
        }

        public virtual float X
        {
            get
            {
                return Location.X;
            }
            set
            {
                Location = new Vector2(value, _location.Y);
            }
        }

        public virtual float Y
        {
            get
            {
                return Location.Y;
            }
            set
            {
                Location = new Vector2(_location.X, value);
            }
        }

        Rectangle _sourceRectangle = new Rectangle(0, 0, 1, 1);
        public virtual Rectangle SourceRectangle
        {
            get
            {
                return _sourceRectangle;
            }
            set
            {
                if (_sourceRectangle != value)
                {
                    _sourceRectangle = value;
                    base.NeedsUpdate = true;
                }
            }
        }

        public virtual int SourceX
        {
            get
            {
                return _sourceRectangle.X;
            }
            set
            {
                this.SourceRectangle = new Rectangle(value, _sourceRectangle.X, _sourceRectangle.Width, _sourceRectangle.Height);
            }
        }

        public virtual int SourceY
        {
            get
            {
                return _sourceRectangle.Y;
            }
            set
            {
                this.SourceRectangle = new Rectangle(_sourceRectangle.X, value, _sourceRectangle.Width, _sourceRectangle.Height);
            }
        }

        public virtual int Width
        {
            get
            {
                return _sourceRectangle.Width;
            }
            set
            {
                this.SourceRectangle = new Rectangle(_sourceRectangle.X, _sourceRectangle.X, value, _sourceRectangle.Height);
            }
        }

        public virtual int Height
        {
            get
            {
                return _sourceRectangle.Height;
            }
            set
            {
                this.SourceRectangle = new Rectangle(_sourceRectangle.X, _sourceRectangle.X, _sourceRectangle.Width, value);
            }
        }

        Rectangle _bounds = Rectangle.Empty;
        public Rectangle Bounds
        {
            get
            {
                return _bounds;
            }
            protected set
            {
                _bounds = value;
            }
        }

        Color _tintColor = Color.White;
        public virtual Color TintColor
        {
            get
            {
                return _tintColor;
            }
            set
            {
                _tintColor = value;
            }
        }

        public bool IntersectsBounds(Rectangle rectangle)
        {
            return _bounds.Intersects(rectangle);
        }

        public bool IntersectsBounds(IBasicSpriteComponent component)
        {
            return _bounds.Intersects(component.Bounds);
        }

        public bool IntersectsPixels(IBasicSpriteComponent component)
        {
            if (!IntersectsBounds(component)) return false;
            return DrawingHelper.PixelsIntersect(_bounds, _textureInformation.PixelsCache, component.Bounds, component.TextureInformation.PixelsCache);
        }

        protected internal virtual void OnLocationChanged()
        {
            LocationChanged.SafeInvoke(this, new EventArgs());
        }

        protected internal virtual void OnSizeChanged()
        {
            SizeChanged.SafeInvoke(this, new EventArgs());
        }

        #endregion

    }

}
